Skip to content

test(scripts): enforce that changeset's ignore covers every private package - #555

Merged
jo-duchan merged 2 commits into
mainfrom
test/changeset-ignore-covers-private
Aug 14, 2026
Merged

test(scripts): enforce that changeset's ignore covers every private package#555
jo-duchan merged 2 commits into
mainfrom
test/changeset-ignore-covers-private

Conversation

@jo-duchan

@jo-duchan jo-duchan commented Aug 14, 2026

Copy link
Copy Markdown
Owner

Summary

Closes #540. .changeset/config.json's ignore has to name every private workspace package and nothing checked that it did — the list fell behind twice in one week, both times caught by a human reading the diff.

Two of the four private packages are not under packages/ at all, so this uses @manypkg/get-packages, the enumerator changesets itself uses. A check that walked packages/* would have declared the list complete while missing half of what it is about.

The review then found the guard had the hole it was written to close. Its header said the damage was "no release note, with the CI job green", and neither half was closed: a changeset naming only ignored packages passes the gate, produces no release, and is deleted by changeset version — the mistake AGENTS.md warns about by name. Adding the private packages to ignore made that quieter rather than louder, since it no longer even bumps an unpublished package. Also fixed: ignoredPackages() read a relative path inside a bare catch, so a non-root cwd silently disabled the mixed-changeset check, and the new test read the config itself rather than through that function — green under exactly the conditions that break the gate.

Checklist

  • Tests written and passing — 5 new, 294 in the scripts suite; 6 mutations run, all killed
  • No any
  • Interface changes land in agent-core first — n/a
  • No sensitive info (tokens, paths, credentials)

Related .work/ docs

.work/reviews/test__changeset-ignore-covers-private.md — one lens, findings and dispositions, the deliberate non-fix (ignore entries are micromatch patterns and this compares literals: loud and safe, so stated as a constraint rather than filed), and a rule violation worth recording.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Updated release validation to reject changesets that only reference ignored packages.
    • Improved handling of changeset configuration errors instead of silently ignoring them.
    • Added validation to keep private-package ignore settings consistent and free of stale entries.
  • Tests

    • Expanded coverage for ignored-only, mixed, published, and malformed changesets.
    • Added checks for private-package configuration consistency.

jo-duchan and others added 2 commits August 14, 2026 23:47
…ackage

The list fell behind twice in one week. #537 wrote a changeset naming
@tapflowio/test-utils, which is private and was absent from ignore -- changeset
version would have versioned an unpublished package and written it a CHANGELOG
while no published package got a release note, with the CI gate green. The
follow-up added test-utils and left @tapflowio/docs in the same state. Both were
caught by a human reading the diff.

Nothing objects on its own: privatePackages.version defaults to true, so an
unignored private package appears in `pnpm changeset` like any other, and config
validation only errors when a non-private unskipped package depends on a skipped
one.

Three assertions, found by inspection rather than from a list -- a list is
satisfied by not being edited, which is how both misses survived
changesetGateAccuracy.test.mjs, whose IGNORED fixture did not move when the real
list did.

Two of the four private packages are not under packages/ at all: pnpm-workspace
picks up `playground` and `docs` separately. A check that walked packages/*
would have declared the list complete while missing half of what it is about, so
this uses @manypkg/get-packages -- the enumerator changesets itself uses, now an
explicit devDependency. Reimplementing the tool's discovery to guard the tool's
behaviour is the shape contributing/test-and-guard-coverage.md calls a floor
rather than a fence.

The reverse direction is asserted too: an entry naming a package that has been
published since, renamed or deleted exempts nothing while reading as deliberate,
and what it hides is a package quietly not getting release notes.
SHIPS_DESPITE_PRIVATE is read from check-changeset.mjs rather than restated, so
the two lists cannot drift.

Closes #540.

<!-- no-changeset: scripts and a root devDependency only, no published source -->

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Adversarial review of 04d60a4. Three holes, all in the guard rather than around it.

The header said the #537 damage was "no published package got a release note,
with the CI changeset job green", and the commit closed neither half of that
sentence. `if (added.length > 0)` accepts any changeset; mixedChangesets only
catches a file naming both sides. A changeset naming *only* ignored packages
sails through -- assemble-release-plan produces no release for it and changeset
version deletes the file, so published source ships with nothing written about
it. That is the mistake the root AGENTS.md warns about by name: a dashboard
change must name @tapflowio/relay.

Adding the private packages to ignore made it quieter, not louder. Before, such
a changeset at least bumped an unpublished package and wrote it a CHANGELOG,
visible in the release PR's diff. Now it emits nothing. ignoredOnlyChangesets
closes it, beside the mixed check it is the other half of.

ignoredPackages() read a relative path inside a bare catch, so any invocation
whose cwd was not the repo root returned "nothing is ignored" -- switching off
the mixed check that exists because four mixed changesets stopped the v0.18.0
release. The new test read the config itself, so it was green under exactly the
conditions that break the gate. It now goes through that function, and the
function fails loudly instead of open.

And the anti-vacuity floor was `> 0` against a measured 4. Swapping getPackages
for a packages/* walk finds 2 of the 4 and every assertion still passes -- the
one enumerator failure the header says getPackages was chosen to prevent.
Floor is the measured count now. `private === true` was also stricter than
changesets' own shouldSkipPackage, which tests truthiness.

Six mutations run, all killed, including one proving the guard now observes the
reader it guards.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@vercel

vercel Bot commented Aug 14, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
tapflow-docs Ignored Ignored Preview Aug 14, 2026 3:09pm

Request Review

@coderabbitai

coderabbitai Bot commented Aug 14, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 8e71a19f-bb69-453e-b5b0-bae7c9ce5529

📥 Commits

Reviewing files that changed from the base of the PR and between 4357ad6 and 3409997.

⛔ Files ignored due to path filters (1)
  • pnpm-lock.yaml is excluded by !**/pnpm-lock.yaml, !pnpm-lock.yaml
📒 Files selected for processing (4)
  • package.json
  • scripts/__tests__/changesetGateAccuracy.test.mjs
  • scripts/__tests__/changesetIgnoresPrivate.test.mjs
  • scripts/check-changeset.mjs

📝 Walkthrough

Walkthrough

The changeset gate now rejects branches whose added changesets affect only ignored packages. Tests validate ignored-only detection and ensure .changeset/config.json covers all private workspace packages.

Changes

Changeset validation

Layer / File(s) Summary
Ignored-only changeset gate
scripts/check-changeset.mjs, scripts/__tests__/changesetGateAccuracy.test.mjs
The checker reads configuration relative to the module, exports SHIPS_DESPITE_PRIVATE, detects ignored-only changesets, and rejects branches without a shipping package. Tests cover ignored, published, mixed, and frontmatter-free changesets.
Private package ignore coverage
package.json, scripts/__tests__/changesetIgnoresPrivate.test.mjs
The test suite discovers workspace packages and verifies complete ignore coverage, stale-entry rejection, and consistency with SHIPS_DESPITE_PRIVATE.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Merge Risk: ⚪ Minimal · up to 34099

This localized change adds validation and tests for private-package changeset coverage; no actionable merge-blocking risk remains after normal checks and review.

Sequence Diagram(s)

sequenceDiagram
  participant PRGate
  participant ignoredPackages
  participant ignoredOnlyChangesets
  participant AddedChangesets
  PRGate->>ignoredPackages: Read ignored package names
  PRGate->>AddedChangesets: Collect added changeset files
  PRGate->>ignoredOnlyChangesets: Check package names
  ignoredOnlyChangesets-->>PRGate: Return ignored-only changesets
  PRGate-->>PRGate: Reject when all added changesets are ignored-only
Loading

Possibly related issues

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description check ✅ Passed The description includes the required summary, checklist, related documentation, testing status, and rationale for no changeset.
Title check ✅ Passed The title clearly identifies the main change: enforcing complete private-package coverage in the changeset ignore list.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/changeset-ignore-covers-private

Comment @coderabbitai help to get the list of available commands.

@jo-duchan
jo-duchan merged commit d3dc0e8 into main Aug 14, 2026
10 checks passed
@jo-duchan
jo-duchan deleted the test/changeset-ignore-covers-private branch August 14, 2026 15:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

changeset: nothing enforces that ignore covers every private package

1 participant